﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms.DataVisualization.Charting;
using MacomberMapSystem.Common.Integration;

namespace MacomberMapSystem.Common.Internals
{
    /// <summary>
    /// This class provides a color rotator, going through a series of colors
    /// </summary>
    public class MM_Color_Rotator
    {
        #region Variable declarations
        private static Dictionary<ChartColorPalette, Color[]> ColorPallettes = InitializePalette();

        /// <summary>Our current color</summary>
        private int CurrentColor = 0;

        /// <summary>Our collection of available colors</summary>
        private Color[] AvailableColors;
        #endregion

        #region Initialization
        /// <summary>
        /// Initialize our dictionary of pallettes
        /// </summary>
        private static Dictionary<ChartColorPalette, Color[]> InitializePalette()
        {
            Dictionary<ChartColorPalette, Color[]> OutDic = new Dictionary<ChartColorPalette, Color[]>();
            OutDic.Add(ChartColorPalette.BrightPastel, new Color[] { Color.FromArgb(0x41, 140, 240), Color.FromArgb(0xfc, 180, 0x41), Color.FromArgb(0xe0, 0x40, 10), Color.FromArgb(5, 100, 0x92), Color.FromArgb(0xbf, 0xbf, 0xbf), Color.FromArgb(0x1a, 0x3b, 0x69), Color.FromArgb(0xff, 0xe3, 130), Color.FromArgb(0x12, 0x9c, 0xdd), Color.FromArgb(0xca, 0x6b, 0x4b), Color.FromArgb(0, 0x5c, 0xdb), Color.FromArgb(0xf3, 210, 0x88), Color.FromArgb(80, 0x63, 0x81), Color.FromArgb(0xf1, 0xb9, 0xa8), Color.FromArgb(0xe0, 0x83, 10), Color.FromArgb(120, 0x93, 190) });
            OutDic.Add(ChartColorPalette.Chocolate, new Color[] { Color.Sienna, Color.Chocolate, Color.DarkRed, Color.Peru, Color.Brown, Color.SandyBrown, Color.SaddleBrown, Color.FromArgb(0xc0, 0x40, 0), Color.Firebrick, Color.FromArgb(0xb6, 0x5c, 0x3a) });
            OutDic.Add(ChartColorPalette.Bright, new Color[] { Color.Green, Color.Blue, Color.Purple, Color.Lime, Color.Fuchsia, Color.Teal, Color.Yellow, Color.Gray, Color.Aqua, Color.Navy, Color.Maroon, Color.Red, Color.Olive, Color.Silver, Color.Tomato, Color.Moccasin });
            OutDic.Add(ChartColorPalette.EarthTones, new Color[] { Color.FromArgb(0xff, 0x80, 0), Color.DarkGoldenrod, Color.FromArgb(0xc0, 0x40, 0), Color.OliveDrab, Color.Peru, Color.FromArgb(0xc0, 0xc0, 0), Color.ForestGreen, Color.Chocolate, Color.Olive, Color.LightSeaGreen, Color.SandyBrown, Color.FromArgb(0, 0xc0, 0), Color.DarkSeaGreen, Color.Firebrick, Color.SaddleBrown, Color.FromArgb(0xc0, 0, 0) });
            OutDic.Add(ChartColorPalette.Excel, new Color[] { Color.FromArgb(0x99, 0x99, 0xff), Color.FromArgb(0x99, 0x33, 0x66), Color.FromArgb(0xff, 0xff, 0xcc), Color.FromArgb(0xcc, 0xff, 0xff), Color.FromArgb(0x66, 0, 0x66), Color.FromArgb(0xff, 0x80, 0x80), Color.FromArgb(0, 0x66, 0xcc), Color.FromArgb(0xcc, 0xcc, 0xff), Color.FromArgb(0, 0, 0x80), Color.FromArgb(0xff, 0, 0xff), Color.FromArgb(0xff, 0xff, 0), Color.FromArgb(0, 0xff, 0xff), Color.FromArgb(0x80, 0, 0x80), Color.FromArgb(0x80, 0, 0), Color.FromArgb(0, 0x80, 0x80), Color.FromArgb(0, 0, 0xff) });
            OutDic.Add(ChartColorPalette.Fire, new Color[] { Color.Gold, Color.Red, Color.DeepPink, Color.Crimson, Color.DarkOrange, Color.Magenta, Color.Yellow, Color.OrangeRed, Color.MediumVioletRed, Color.FromArgb(0xdd, 0xe2, 0x21) });
            OutDic.Add(ChartColorPalette.Berry, new Color[] { Color.BlueViolet, Color.MediumOrchid, Color.RoyalBlue, Color.MediumVioletRed, Color.Blue, Color.BlueViolet, Color.Orchid, Color.MediumSlateBlue, Color.FromArgb(0xc0, 0, 0xc0), Color.MediumBlue, Color.Purple });

            //Initialize our gray scale colors
            Color[] GrayColors = new Color[0x10];
            for (int i = 0; i < GrayColors.Length; i++)
                GrayColors[i] = Color.FromArgb(200 - (i * 11), 200 - (i * 11), 200 - (i * 11));
            OutDic.Add(ChartColorPalette.Grayscale, GrayColors);

            OutDic.Add(ChartColorPalette.Light, new Color[] { Color.Lavender, Color.LavenderBlush, Color.PeachPuff, Color.LemonChiffon, Color.MistyRose, Color.Honeydew, Color.AliceBlue, Color.WhiteSmoke, Color.AntiqueWhite, Color.LightCyan });
            OutDic.Add(ChartColorPalette.Pastel, new Color[] { Color.SkyBlue, Color.LimeGreen, Color.MediumOrchid, Color.LightCoral, Color.SteelBlue, Color.YellowGreen, Color.Turquoise, Color.HotPink, Color.Khaki, Color.Tan, Color.DarkSeaGreen, Color.CornflowerBlue, Color.Plum, Color.CadetBlue, Color.PeachPuff, Color.LightSalmon });
            OutDic.Add(ChartColorPalette.SeaGreen, new Color[] { Color.SeaGreen, Color.MediumAquamarine, Color.SteelBlue, Color.DarkCyan, Color.CadetBlue, Color.MediumSeaGreen, Color.MediumTurquoise, Color.LightSteelBlue, Color.DarkSeaGreen, Color.SkyBlue });
            OutDic.Add(ChartColorPalette.SemiTransparent, new Color[] { Color.FromArgb(150, 0xff, 0, 0), Color.FromArgb(150, 0, 0xff, 0), Color.FromArgb(150, 0, 0, 0xff), Color.FromArgb(150, 0xff, 0xff, 0), Color.FromArgb(150, 0, 0xff, 0xff), Color.FromArgb(150, 0xff, 0, 0xff), Color.FromArgb(150, 170, 120, 20), Color.FromArgb(80, 0xff, 0, 0), Color.FromArgb(80, 0, 0xff, 0), Color.FromArgb(80, 0, 0, 0xff), Color.FromArgb(80, 0xff, 0xff, 0), Color.FromArgb(80, 0, 0xff, 0xff), Color.FromArgb(80, 0xff, 0, 0xff), Color.FromArgb(80, 170, 120, 20), Color.FromArgb(150, 100, 120, 50), Color.FromArgb(150, 40, 90, 150) });
            return OutDic;
        }



        /// <summary>
        /// Initialize our gray scale colors
        /// </summary>
        /// <param name="SkipExistingColors">Whether to skip colors within our voltage levels</param>
        /// <returns></returns>
        public MM_Color_Rotator(bool SkipExistingColors)
        {
            List<Color> ColorsToSkip = new List<Color>();            
            if (SkipExistingColors)
                foreach (MM_KVLevel VoltageLevel in Data_Manager.KVLevels.Values)
                    if (!ColorsToSkip.Contains(VoltageLevel.Energized.ForeColor))
                        ColorsToSkip.Add(VoltageLevel.Energized.ForeColor);
            
            List<Color> OutColors = new List<Color>();
            foreach (Color[] ColorsToParse in ColorPallettes.Values)
                foreach (Color ColorToParse in ColorsToParse)
                    if (!ColorsToSkip.Contains(ColorToParse) && !OutColors.Contains(ColorToParse))
                        OutColors.Add(ColorToParse);
            this.AvailableColors = OutColors.ToArray();
        }
        #endregion

        /// <summary>
        /// Return the next color in our array
        /// </summary>
        /// <returns></returns>
        public Color NextColor()
        {
            Color OutColor = AvailableColors[CurrentColor];
            CurrentColor = (CurrentColor + 1) % AvailableColors.Length;
            return OutColor;
        }
    }

}
